package cc.z8g.browser.core.bookmark

import android.app.Activity
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.util.LruCache
import android.widget.ImageView
import cc.z8g.browser.BrowserApp
import cc.z8g.browser.R
import cc.z8g.browser.database.Bookmark
import cc.z8g.browser.extensions.themedDrawable
import cc.z8g.browser.favicon.FaviconModel
import cc.z8g.browser.utils.FileUtils
import cc.z8g.browser.utils.ThemeUtils
import cc.z8g.browser.utils.ThreadPool
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign
import io.reactivex.rxjava3.kotlin.subscribeBy

/**
 * An image loader implementation that caches icons in memory after reading them from the disk
 * cache.
 */
class FaviconImageLoader(activity: Activity)  {

    private val lruCache: LruCache<String, Any> =
        object : LruCache<String, Any>(FileUtils.megabytesToBytes(5).toInt()) {
            override fun sizeOf(key: String, value: Any) = when (value) {
                is Bitmap -> value.allocationByteCount
                else -> 1
            }
        }
    private val folderIcon = BrowserApp.getApplication().themedDrawable(
        R.drawable.ic_folder, ThemeUtils.getColor(activity, R.attr.autoCompleteTitleColor)
    )
    private val webPageIcon = BrowserApp.getApplication().themedDrawable(
        R.drawable.ic_webpage, ThemeUtils.getColor(activity, R.attr.autoCompleteTitleColor)
    )
    private val compositeDisposable = CompositeDisposable()

    fun loadImage(imageView: ImageView, bookmark: Bookmark) {
        imageView.tag = bookmark.url
        lruCache[bookmark.url]?.let {
            if (it is Bitmap) {
                imageView.setImageBitmap(it)
            } else if (it is Drawable) {
                imageView.setImageDrawable(it)
            }
        } ?: run {
            when (bookmark) {
                is Bookmark.Folder -> {
                    lruCache.put(bookmark.url, folderIcon)
                    imageView.setImageDrawable(folderIcon)
                }
                is Bookmark.Entry -> {
                    lruCache.put(bookmark.url, webPageIcon)
                    imageView.setImageDrawable(webPageIcon)
                    compositeDisposable += FaviconModel
                        .faviconForUrl(bookmark.url, bookmark.title)
                        .subscribeOn(ThreadPool.getNetworkScheduler())
                        .observeOn(ThreadPool.getMainScheduler())
                        .subscribeBy(
                            onSuccess = { bitmap ->
                                lruCache.put(bookmark.url, bitmap)
                                if (imageView.tag == bookmark.url) {
                                    imageView.setImageBitmap(bitmap)
                                }
                            }
                        )
                }
            }
        }

        fun cleanup() {
            compositeDisposable.clear()
        }
    }
}
